﻿cbuffer cbPerObject
{
	float4x4 WorldViewProjection;	
	float4x4 WorldView;	
	float4x4 View;	
	float4x4 InverseProjection;

	float2 _terrainSize;
}
cbuffer cbGlobal
{
	float zFar;
}
struct App2VS
{
	float3 position : POSITION;
	float3 color : COLOR;
	float3 normal : NORMAL;
	//float2 uv : TEXCOORD0;
};

struct VS2PS
{
	float4 position : SV_Position;
	float4 color : Albedo;
	float3 normal : Normal;
	float depth : Depth;
};
struct PS2GPU
{
	float depth : SV_Target0;
	float4 albedo : SV_Target1;
	float3 normal : SV_Target2;
};
//from http://aras-p.info/texts/CompactNormalStorage.html#method04spheremap
#define kPI 3.1415926536f
float2 encodeNormal (float3 n)
{
	return float4((float2(atan2(n.y,n.x)/kPI, n.z)+1.0)*0.5,0,0);
}

Texture2D _heightTexture;

void vs(App2VS IN, out VS2PS OUT)
{

	float2 uv = IN.position.xz;
	float height = _heightTexture.Load(float3(uv, 1)).r;
	float4 pos = float4(IN.position.x, height, IN.position.z, 1);
	OUT.position = mul(pos, WorldViewProjection);
	OUT.normal = mul(IN.normal, (float3x3)WorldView);
	OUT.depth = mul(pos, WorldView).z;
	OUT.color = 1;
}

void ps(VS2PS IN, out PS2GPU OUT)
{
	float nMax = max(max(abs(IN.normal.x), abs(IN.normal.y)), abs(IN.normal.z));

	OUT.normal = IN.normal / nMax;//encodeNormal(IN.normal);
	//OUT.normal = encodeNormal(IN.normal);
	//store linear depth to 0->1
	OUT.depth = IN.depth / zFar;
	OUT.albedo = IN.color;
}

technique10 Render
{
	pass P0
	{
		SetGeometryShader( 0 );
		SetVertexShader( CompileShader( vs_4_0, vs() ) );
		SetPixelShader( CompileShader( ps_4_0, ps() ) );
	}
}